package com.jml.service.order.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.jml.service.order.openfeign.MemberServiceFeign;

import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;


@RestController
@Slf4j
public class OrderService {
    @Autowired
    private MemberServiceFeign memberServiceFeign;
    // 限流规则名称
    private static final String GETORDER_KEY = "orderToMember";

    /**
     * 基于我们的fegin客户端形式实现rpc远程调用
     *
     * @return
     */
    @RequestMapping("/orderFeignToMember")
    public String orderFeignToMember() {
        String result = memberServiceFeign.getUser(1);
        return "我是订单服务调用会员服务的接口,返回结果" + result;
    }

    @RequestMapping("/")
    public String order() {
        return "订单服务";
    }

    @RequestMapping("/orderToMember")
    public String orderToMember() {
        Entry entry = null;
        try {
            //这是手动代码使用我们配置的限流，我们可以使用aop优化
            entry = SphU.entry(GETORDER_KEY);
            System.out.println(LocalDateTime.now()+"orderToMember接口");
            return "orderToMember接口";
        } catch (Exception e) {
            // 限流的情况就会进入到Exception
            System.out.println(LocalDateTime.now()+"当前访问人数过多，请稍后重试!");
            return "当前访问人数过多，请稍后重试!";
        } finally {
            // SphU.entry(xxx) 需要与 entry.exit() 成对出现,否则会导致调用链记录异常
            if (entry != null) {
                entry.exit();
            }
        }


    }

    /**
     * fallback 服务降级执行本本地方法
     * blockHandler 限流/熔断出现异常执行的方法
     * value 指定我们的资源的名称
     */
    @SentinelResource(value = GETORDER_KEY, blockHandler = "getOrderQpsException")
    @RequestMapping("/orderToMemberSentinelResource")
    public String orderToMemberSentinelResource() {
        return "orderToMemberSentinelResource";
    }

    /**
     * 被限流后返回的提示
     */
    public String getOrderQpsException(BlockException e) {
        e.printStackTrace();
        return "该接口已经被限流啦!";
    }



    /**
     * 基于我们的控制创建规则实现限流
     * 在没有使用注解的情况下，在控制台配置的资源名应该是路径地址
     */
    @RequestMapping("/getOrderConsole")
    public String getOrderConsole() {
        return "getOrderConsole";
    }

    /**
     * 基于控制台+自定义提示还是要用注解
     * @return
     */
    @SentinelResource(value = "getOrderConsole001", blockHandler = "getOrderQpsException")
    @RequestMapping("/getOrderConsolexxx")
    public String getOrderConsole1() {
        return "getOrderConsolexxx";
    }

//每次最多只会有一个线程处理该业务逻辑，超出该阈值的情况下，直接拒绝访问。
    @SentinelResource(value = "getOrderSemaphore", blockHandler = "getOrderQpsException")
    @RequestMapping("/getOrderSemaphore")
    public String getOrderSemaphore() {
        try {
            Thread.sleep(5000);
        } catch (Exception e) {

        }
        log.info(Thread.currentThread().getName());
        return "getOrderSemaphore";
    }

    //持久化，从nacos读取
    @SentinelResource(value = "getOrderSentinel", blockHandler = "getOrderQpsException")
    @RequestMapping("/getOrderSentinel")
    public String getOrderSentinel() {
        return "getOrderSentinel";
    }


    /**
     * 基于我们的平均响应时间实现降级
     * 如果一秒内访问5次，平均响应时间超过我们平台设置的阈值，直接触发我们的熔断执行我们服务降级的方法。
     */
    @SentinelResource(value = "getOrderDowngradeRtType", fallback = "getOrderDowngradeRtTypeFallback")
    @RequestMapping("/getOrderDowngradeRtType")
    public String getOrderDowngradeRtType() {
        try {
            Thread.sleep(300);
        } catch (Exception e) {

        }
        return "正常执行我们业务逻辑";
    }
    public String getOrderDowngradeRtTypeFallback() {
        return "执行我们本地的服务降级的方法";
    }

    /**
     * 异常比例
     * @param age
     * @return
     */
    @SentinelResource(value = "getOrderDowngradeErrorType", fallback = "getOrderDowngradeErrorTypeFallback")
    @RequestMapping("/getOrderDowngradeErrorType")
    public String getOrderDowngradeErrorType(int age) {
        int j = 1 / age;
        return "正常执行我们的业务逻辑";
    }

    public String getOrderDowngradeErrorTypeFallback(int age) {
        return "服务降级啦，当前服务器请求次数过多，请稍后重试!";
    }
}
